home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / wdj0797.zip / TUFFS.ZIP / EXCEPT9.CPP < prev    next >
C/C++ Source or Header  |  1997-04-22  |  4KB  |  163 lines

  1. // File:        except9.cpp
  2. // Description: Shows how to implement an exception-safe private
  3. //              heap manager under Win32.
  4. //
  5. // Notes:       Relies on the STL, which means it will only compile under
  6. //              BC++5.0 and later.
  7. //
  8. #include <iostream.h>
  9. #include <except.h>
  10. #include <cstring.h>
  11. #include <map.h>
  12.  
  13. using namespace std;
  14.  
  15. class TBuffer;
  16.  
  17. // Listing 6 Begin
  18. class TPrivateHeap
  19. {
  20. public:
  21.   TPrivateHeap(size_t initialSize = 0x10000, DWORD flags = 0);
  22.   virtual ~TPrivateHeap();
  23.   virtual void* Allocate(size_t size, TBuffer* buffer);
  24.   virtual void  Free(void* p);
  25.   virtual void  Reset();
  26. protected:
  27.   size_t OriginalSize;
  28.   HANDLE Handle;
  29.   DWORD  Flags;
  30.   // Use STL map class to track allocations that have been made from
  31.   // this private heap so it can be restored in case of a failure.
  32.   // The map is indexed by the address of the block in the heap
  33.   // so it can be freed efficiently during normal operation, and its
  34.   // value is the size of the block for restoration purposes.
  35.   typedef map<void*, TBuffer*, less<void*> > HeapMap;
  36.   HeapMap Allocated;
  37. };
  38. // Listing 6 End
  39.  
  40. // Listing 7 Begin
  41. class TBuffer
  42. {
  43.   friend class TPrivateHeap;
  44. public:
  45.   TBuffer(size_t size, TPrivateHeap &heap, char init = 0);
  46.   ~TBuffer();
  47.   virtual operator char*();
  48. protected:
  49.   TPrivateHeap &Heap;
  50.   size_t Size;
  51.   char   Init;
  52.   void*  Buffer;
  53. };
  54. // Listing 7 End
  55.  
  56. TPrivateHeap::TPrivateHeap(size_t initialSize, DWORD flags):
  57.   Flags(flags), OriginalSize(initialSize)
  58. {
  59.   // Construct a Win32 private heap with the initial size as given.
  60.   Handle = HeapCreate(0, initialSize, 0);
  61. }
  62.  
  63. TPrivateHeap::~TPrivateHeap()
  64. {
  65.   HeapDestroy(Handle);
  66. }
  67.  
  68. void* TPrivateHeap::Allocate(size_t size, TBuffer* buffer)
  69. {
  70.   // Record the presence of the block.
  71.   void* result = HeapAlloc(Handle, Flags, size);
  72.   Allocated[result] = buffer;
  73.   return result;
  74. }
  75.  
  76. void TPrivateHeap::Free(void* p)
  77. {
  78.   HeapFree(Handle, Flags, p);
  79.   Allocated.erase(p);
  80. }
  81.  
  82. // Listing 9 Begin
  83. void TPrivateHeap::Reset()
  84. {
  85.   // The heap is wrecked.  Restore it.
  86.   HeapDestroy(Handle);
  87.   Handle = HeapCreate(Flags, OriginalSize, 0);
  88.   // Recreate all the objects that should be on the heap
  89.   // so that problems don't occur during subsequent access.
  90.   HeapMap::iterator i;
  91.   for (i = Allocated.begin(); i != Allocated.end(); i++)
  92.   {
  93.     cout << "Recreating block (" << (*i).second << ", " << (*i).second->Size << ")" << endl;
  94.     void* result = HeapAlloc(Handle, Flags, (*i).second->Size);
  95.     memset(result, (*i).second->Init, (*i).second->Size);
  96.     (*i).second->Buffer = result;
  97.   }
  98. }
  99. // Listing 9 End
  100.  
  101. TBuffer::TBuffer(size_t size, TPrivateHeap &heap, char init): Heap(heap), Size(size), Init(init)
  102. {
  103.   Buffer = heap.Allocate(size, this);
  104.   memset(Buffer, init, size);
  105. };
  106.  
  107. TBuffer::~TBuffer()
  108. {
  109.   Heap.Free(Buffer);
  110. }
  111.  
  112. TBuffer::operator char*()
  113. {
  114.   return (char*)Buffer;
  115. }
  116.  
  117. static TPrivateHeap heap;
  118.  
  119. void badFunction()
  120. {
  121.   TBuffer p(10, heap);
  122.   cout << "Setting p to zero..." << endl;
  123.   memset(p, 0, -10);
  124. }
  125.  
  126.  
  127. int main()
  128. {
  129.   // Listing 8 Begin
  130.   TBuffer b(20, heap);
  131.   for (int i=0; i<2; i++)
  132.   {
  133.     DWORD code = 0;
  134.     // Make sure that the "b" buffer is still functional.
  135.     memset(b, i, 20);
  136.     cout << "Before badFunction: b[0] == " << (int)b[0] << endl;
  137.     // Allocate a heap-based buffer object, just to make things
  138.     // more interesting (this one leaks, but can be re-created!
  139.     TBuffer* c = new TBuffer(30, heap);
  140.     try
  141.     {
  142.       try
  143.       {
  144.         cout << "Calling badFunction()" << endl;
  145.         badFunction();
  146.         delete c;
  147.         cout << "badFunction() completed without exception" << endl;
  148.       } catch (xmsg &x) {
  149.         cerr << "Exception caught '" << x.why() << "'" << endl;
  150.       } catch (...) {
  151.         cerr << "Unknown exception caught" << endl;
  152.       }
  153.     } __except (code=GetExceptionCode(), 1) {
  154.       cerr << "Unknown system exception " << hex << code << " caught" << endl;
  155.       heap.Reset();
  156.     }
  157.     cout << "After BadFunction: b[0] == " << (int)b[0] << endl;
  158.   }
  159.   // Listing 8 End
  160.   return 0;
  161. }
  162.  
  163.